package com.itheima.service.impl;


import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.dto.PhoneCodeDto;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import com.itheima.vo.LoginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public boolean sendMsg(String phone) {
        //1.生成验证码
        //四位数
        int number = new Random().nextInt(8999) + 1000;

        log.info("验证码：" + number);

        //2.将验证码写入到Redis
        //2.1导入Redis坐标依赖
        //2.2检查Redis配置
        //2.3启动本地的Redis服务
        //2.4注入 RedisTemplate
        //2.5通过 redisTemplate.opsForValue().set()写入数据
        //                                  设置过期时间，因为是long类型，所以2L
        redisTemplate.opsForValue().set("CODE" + phone, number + "", 2L, TimeUnit.HOURS);
        //另一种过期时间设置方法
        //redisTemplate.expire("", Duration.ofDays(2));
        //3.发送验证码

        return true;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public LoginVo login(PhoneCodeDto dto) {

        //1.校验入参   全为空    验证码为空    手机号为空
        if (dto == null || StringUtils.isEmpty(dto.getCode()) || StringUtils.isEmpty(dto.getPhone())) {
            throw new RuntimeException("入参不能为空");
        }


        String phone = dto.getPhone();

        //2. 校验验证码
        //2.1 从redis读取之前发送的验证码

        String codeFromRedis = redisTemplate.opsForValue().get("CODE" + phone);
        if (StringUtils.isEmpty(codeFromRedis)) {
            throw new RuntimeException("验证码为空");
        }
        //2.2 从dto中获取用户提交的验证码
        String code = dto.getCode();

        //2.3 对比两个验证码
        if (!codeFromRedis.equals(code)) {
            throw new RuntimeException("验证码不正确");
        }

        //3. 检测手机号是否存在
        //3.1 创建user的实体类mapper
        //3.2 调用UserMapper.selectByPhone方法
        User user = userMapper.selectByPhone(phone);
        //5.如果不存在，则创建账号，生成token，写入Redis
        if (user == null) {
            //5.1 组装user对象
            User newuser = new User();
            newuser.setId(IdUtil.getSnowflakeNextIdStr());
            newuser.setPhone(phone);
            newuser.setName("用户" + code);
            newuser.setSex("男");
            newuser.setIdNumber("");
            newuser.setAvatar("");
            newuser.setStatus(1);

            //5.2 调用userMapper.insert
            int insertRes = userMapper.insert(newuser);
            if (insertRes != 1) {
                throw new RuntimeException("新用户注册失败");
            }
            user = new User();
            //5.3 把当前创建的用户信息，赋值到user对象中
            BeanUtils.copyProperties(newuser, user);

        }

        //4. 如果粗你在，则生成token，写入Redis
        //4.1 生成token(无规则、唯一、有过期时间)
        String token = System.currentTimeMillis() + "";

        //4.2 将token储存到Redis里面
        //目的：通过token可以找到token对应的用户信息
        //注意:如果你想把一个对象存到Redis的话，那么最好先转成json再存进去
        //                                        用fastJson依赖转换      设置过期时间---7天
        redisTemplate.opsForValue().set("user_token" + token, JSON.toJSONString(user), 7L, TimeUnit.DAYS);

        //4.3 组装返回值的Vo结构
        LoginVo vo = new LoginVo();
        vo.setId(user.getId());
        vo.setPhone(user.getPhone());
        vo.setStatus(user.getStatus());
        vo.setToken(token);


        return vo;
    }

    @Override
    public void clearToken(String token) {
        redisTemplate.delete("user_token" + token);
    }
}
